package com.ease.util {

   import flash.events.Event;

   /**
    * This class represents an event indicating some change in an object relationship, e.g.
    * the assignment of a new parent or resetting of the assignment of the current parent of
    * a given object.
    *
    * <p>For the parent example, the use of this event should be unnecessary for display
    * objects, which already have an explicit 'parent' property and such an object's addition
    * or removal is notified through other (flex) framework events. So the event would be
    * mostly useful for the objects that don't have an explicit notion of a parent or a
    * parent property, or their existence is not notified through any other events (that
    * bubble through the system).
    *
    * @internal Specific relationship names/constants (e.g., parent, mediator, etc) are not
    * defined in this class because they are framework or application specific. An app or FW
    * can define (or redefine) them within their own space.
    */
   public class RelationshipUpdateEvent extends ObjectEvent
   {
      /**
       * The event type id that indicates assignment of a role to an object (or resetting
       * of the current role assignment to null) with reference to this.object.
       */
      public static const ROLE_ASSIGNED:String = "roleAssigned";

      /**
       * Initializes an instance of this class.
       *
       * @param type
       *    The id for the event.
       *
       * @param object
       *    Value for the object property.
       *
       * @param relatedObject
       *    The object that is being assigned the new role.
       *
       * @param bubbles
       *    Whether the event should bubble or not.
       */
      public function RelationshipUpdateEvent( type:String = ROLE_ASSIGNED,
                                               object:Object = null,
                                               relatedObject:Object = null,
                                               relationship:String = null,
                                               bubbles:Boolean = true ) {
         super( type, object, bubbles );
         _relatedObject = relatedObject;
         _relationship = relationship;
      }

      //---------------------------------------------------------------------------
      // Class Methods

      /**
       * A convenience factory method to create an instance of this class that represents
       * the assignment of a role to the second object with reference to the first object.
       */
      public static function
         newRoleAssignment( object:Object, relatedObject:Object,
                            relationship:String ):RelationshipUpdateEvent {
         return new RelationshipUpdateEvent( ROLE_ASSIGNED, object, relatedObject,
            relationship );
      }

      /**
       * A convenience factory method to create an instance of this class that represents
       * the unassignment of the currently related entity from its relationship to the given
       * object.
       */
      public static function
         newRoleUnassignment( object:Object, relationship:String ):RelationshipUpdateEvent {
         return new RelationshipUpdateEvent( ROLE_ASSIGNED, object, null, relationship );
      }

      //-------------------------------------------------------
      // Property: relatedObject

      private var _relatedObject:Object;

      /**
       * The object that's being assigned some relationship with (or role for) this.object.
       */
      public function get relatedObject():Object {
         return _relatedObject;
      }

      //-------------------------------------------------------
      // Property: oldRelatedObject

      /**
       * The object that previously was in the said relationship with (or was serving the
       * said role for) this.object. It's optional for the event source to provide this piece
       * of information.
       */
      [Optional]
      public var oldRelatedObject:Object;

      //-------------------------------------------------------
      // Property: relationship

      private var _relationship:String;

      /**
       * The relationship between this.object and this.relatedObject, e.g., if the latter is
       * the parent of the former, then relationship would be "parent".
       */
      public function get relationship():String {
         return _relationship;
      }

      //---------------------------------------------------------------------------
      // Overridden Methods

      /**
       * Creates a clone of this event. All custom events should override this method.
       *
       * @return
       *    A clone of this event.
       */
      public override function clone():Event {
         return new RelationshipUpdateEvent( super.type, super.object, _relatedObject,
            _relationship );
      }
   }

}